#!/bin/bash


:<<memoName

Shell中的函数调用

一、Shell中函数的定义
	为了方便程序和管理和模块化并减少代码的重复，函数是一个很好的可以共用的模块。而Shell中函数的定义有两种方法，如下：
	Shell 函数的本质是一段可以重复使用的脚本代码，这段代码被提前编写好了，放在了指定的位置，使用时直接调取即可。
	Shell 中的函数和C++、Java、Python、C# 等其它编程语言中的函数类似，只是在语法细节有所差别。
	Shell 函数定义的语法格式如下：
		function name() {
			statements
			[return value]
		}
		对各个部分的说明：
		function是 Shell 中的关键字，专门用来定义函数；
		name是函数名；
		statements是函数要执行的代码，也就是一组语句；
		return value表示函数的返回值，其中 return 是 Shell 关键字，专门用在函数中返回一个值；这一部分可以写也可以不写。

		由{ }包围的部分称为函数体，调用一个函数，实际上就是执行函数体中的代码。

	函数调用
		调用 Shell 函数时可以给它传递参数，也可以不传递。如果不传递参数，直接给出函数名字即可：
			name
		如果传递参数，那么多个参数之间以空格分隔：
			name param1 param2 param3
		不管是哪种形式，函数名字后面都不需要带括号。



		function fname()
		{
		statements；
		}
		或
		fname()
		{
		statements;
		}
	注意，()内是没有参数的，它并不像C语言那样，在()里可以有参数。

二、函数的调用、使用
	1、调用外部的函数，直接在本函数内添加
		. fname.sh
		然后：
		fname  #不带参数的
		fname agr1 agr2   #带参数的
	2、本部的函数则可以直接使用
		fname  #不带参数的
		fname agr1 agr2   #带参数的

三、自定义函数
	例如：判断文件是否存在

		function fileExit()
		{
		    filename=$1 ;
		    if [ -e "${filename}" ]
		    then
		        echo $1 " file is exit."
		    else
		        echo $1 " is not exit."
		    fi
		}
		read -p "Please input the file name you want: " file ;
		fileExit $file ;

	例如：根据输入的次数来进行打印 运行后输入打印的次数，即可每个1s进行打印


		function LoopPrint()
		{
		    count=0;
		    while [ $count -lt $1 ];
		    do
		    echo $count;
		    echo $0;
		    let ++count;
		    sleep 1;
		    done
		    return 0;
		}
		read -p "Please input the times of print you want: " n ;
		LoopPrint $n ;

		#函数定义
		function url(){
			echo "http://c.biancheng.net/shell/"
		}
		#函数调用
		url

		你可以将调用放在定义的前面，也就是写成下面的形式：
			#函数调用
			url
			#函数定义
			function url(){
				echo "http://c.biancheng.net/shell/"
			}
		定义一个函数，计算所有参数的和：
			function getsum(){
				local sum=0
				for n in $@
				do
					 ((sum+=n))
				done
				return $sum
			}
			getsum 10 20 55 15  #调用函数并传递参数
			echo $?

			# 递归调用列出文件 文件夹-操作扩展处理
				logDir="./elk/logs/"
				# pwdDir=`pwd`
				# logDir="${pwdDir}/elk/logs/"
				
				function ecmptyFileName(){
					for fileName in $( ls $1 ) ; do
						dirFileName="$1"${fileName}
						# echo ${dirFileName}
						if [ -f "${dirFileName}" ] ; then
							echo "=文件=" ${dirFileName}
						else
							echo "-文件夹-" ${dirFileName}
							ecmptyFileName "${dirFileName}/"
						fi
					done

				}

				ecmptyFileName ${logDir}
				# 递归结果
					-文件夹- ./elk/logs/mysql
					=文件  = ./elk/logs/mysql/mysql-redis-err.log
					=文件  = ./elk/logs/mysql/mysql-redis-slow.log
					-文件夹- ./elk/logs/nginx
					=文件  = ./elk/logs/nginx/api_access.log
					=文件  = ./elk/logs/nginx/api_error.log
					-文件夹- ./elk/logs/php
					-文件夹- ./elk/logs/php/php-fpm-err.log
					-文件夹- ./elk/logs/php/php_errors.log
					-文件夹- ./elk/logs/rabbitmq
					=文件  = ./elk/logs/rabbitmq/crash.log
					-文件夹- ./elk/logs/redis
					=文件  = ./elk/logs/redis/redis.log
					mac@macde % ls -la ./elk/logs/php/php-fpm-err.log
					total 0
					drwxr-xr-x  2 mac  staff   64  4  1 18:53 .
					drwxr-xr-x  6 mac  staff  192  4  1 18:53 ..

关于函数中变量的含义如下：

	$0：是脚本本身的名字；
	$#：是传给脚本的参数个数；
	$@：是传给脚本的所有参数的列表，即被扩展为"$1" "$2" "$3"等；
	$*：是以一个单字符串显示所有向脚本传递的参数，与位置变量不同，参数可超过9个，即被扩展成"$1c$2c$3"，其中c是IFS的第一个字符；
	$$：是脚本运行的当前进程ID号；
	$?：是显示最后命令的退出状态，0表示没有错误，其他表示有错误；

$@表示函数的所有参数，$?表示函数的退出状态（返回值）
此处我们借助 return 关键字将所有数字的和返回，并使用$?得到这个值，这种处理方案在其它编程语言中没有任何问题，但是在 Shell 中是非常错误的，Shell 函数的返回值和其它编程语言大有不同











memoName